#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#include <limits.h>
#include <time.h>
#include <errno.h>
#include <time.h>
#include <signal.h>
#include <malloc.h>
#include <fcntl.h>
#include <unistd.h>
#include <dirent.h>
#include <libgen.h>
#include <termios.h>
#include <pthread.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <sys/wait.h>
#include <sys/types.h>
#include <sys/ioctl.h>
#include <sys/reboot.h>
#include <sys/timerfd.h>
#include <sys/inotify.h>
#include <sys/poll.h>
#include <linux/fb.h>
#include <linux/input.h>
#include <SDL.h>
#include "sandbox.h"

struct sandbox_fb_sdl_context_t {
	SDL_Window * window;
	SDL_Surface * screen;
	char * title;
	int width;
	int height;
};

void * sandbox_fb_sdl_open(const char * title, int width, int height)
{
	struct sandbox_fb_sdl_context_t * ctx;
	Uint32 flags = SDL_WINDOW_SHOWN | SDL_WINDOW_INPUT_FOCUS | SDL_WINDOW_MOUSE_FOCUS;

	ctx = malloc(sizeof(struct sandbox_fb_sdl_context_t));
	if(!ctx)
		return NULL;

	ctx->title = strdup(title ? title : "Xboot Runtime Environment");
	ctx->window = SDL_CreateWindow(ctx->title, SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, width, height, flags);
	if(!ctx->window)
	{
		if(ctx->title)
			free(ctx->title);
		free(ctx);
		return NULL;
	}

	ctx->screen = SDL_GetWindowSurface(ctx->window);
	if(!ctx->screen)
	{
		if(ctx->window)
			SDL_DestroyWindow(ctx->window);
		if(ctx->title)
			free(ctx->title);
		free(ctx);
		return NULL;
	}

	SDL_GetWindowSize(ctx->window, &ctx->width, &ctx->height);
	return ctx;
}


struct surface_t * surface_alloc_wrapper(void * pixels, int width, int height);

struct surface_t * sandbox_fb_sdl_surface_get(void * context)
{
	struct sandbox_fb_sdl_context_t * ctx = (struct sandbox_fb_sdl_context_t *)context;

	return surface_alloc_wrapper(ctx->screen->pixels, ctx->width, ctx->height);
}

void sandbox_fb_sdl_close(void * context)
{
	struct sandbox_fb_sdl_context_t * ctx = (struct sandbox_fb_sdl_context_t *)context;

	if(!ctx)
		return;
	if(ctx->window)
		SDL_DestroyWindow(ctx->window);
	if(ctx->screen)
		SDL_FreeSurface(ctx->screen);
	if(ctx->title)
		free(ctx->title);
	free(ctx);
}

void sandbox_fb_sdl_fb_present(void * context, struct region_list_t * rl)
{
	sandbox_fb_sdl_surface_present(context, (struct sandbox_region_list_t *)rl);
}

int sandbox_fb_sdl_surface_present(void * context, struct sandbox_region_list_t * rl)
{
	struct sandbox_fb_sdl_context_t * ctx = (struct sandbox_fb_sdl_context_t *)context;
	SDL_UpdateWindowSurface(ctx->window);
	return 1;
}